	\chapter{项目涉及的相关知识和技术简介}
	
	\section{深度值}
	深度值存储在深度缓冲之中，代表着渲染生成的物体在屏幕空间坐标上，距离通过OpenGL定义的视口Viewport的远近程度，因此又等价于物体在坐标上的(x, y, z)坐标值中的z值。z值可通过GLSL内置变量FragCoord.z得到，其值越大，物体深度值越大，其距离视口也就越远。
	
	OpenGL会经过一系列的坐标变换，将顶点坐标转化为屏幕上的二位坐标或者像素。而在这一过程中，当所有顶点都经过投影矩阵\cite{kooima2009generalized}的计算，从观察坐标空间转转化到裁剪坐标空间后，透视除法就会开始执行，将坐标的(x, y, z)分别除以其次分量w，从而将4D裁剪空间坐标转化为3D标准化坐标。
	\section{帧缓冲}
	帧缓存是对图形硬件的一种抽象，一个存储单元对应屏幕上的一个像素，整个帧缓冲对应屏幕显示的一帧画面，可以看作为是各种屏幕缓冲的结合，能够包含至多4个颜色缓冲，1个深度缓冲，1个模板缓冲，1个多重采样缓冲，1个积累缓冲。OpenGL采用双帧缓冲机制，一个为“屏幕缓冲”，包含当前正在渲染到屏幕的画面信息，另一个为“离屏缓冲”，包含下一帧的渲染所需的画面信息，当渲染完当前“屏幕缓冲”的内容后，视频控制器指针又会指向当前的“离屏缓冲”，从而实现渲染画面的连续交替。数据经过OpenGL渲染管线处理形成一帧的画面后，会先被存放在“离屏缓冲”中，等待显示器渲染显示。当我们创建窗口时，OpenGL会生成并配置这样一组默认帧缓冲，渲染到默认帧缓冲的画面内容，紧接着就会被渲染到屏幕上。
	
	OpenGL允许开发人员创建自定义的帧缓冲(至少包含1个颜色缓冲)，用于接收经过OpenGL渲染管线处理后的结果，并且自定义帧缓冲中的数据并不会自动渲染到屏幕上。这样的机制为开发人员编写各种后期效果和数据计算提供了极高的灵活性，市面上许多的图像修改工具或滤镜，都是基于这种机制。
	\section{贝塞尔曲线和曲面}
	\subsection{贝塞尔曲线}
	贝塞尔曲线\cite{baydas2019defining}是一种图形学上的数学曲线，通过改变控制点的位置或者权重，来改变对应曲线的走势，相比于传统的直线、圆弧，更加灵活美观，在设计领域有着非常广泛的运用。
\begin{figure}[ht]
    \centering
    \includegraphics[height=2.7cm]{images/贝塞尔曲线.png}
    \caption{贝塞尔曲线}
    \label{fig:my_label}
\end{figure}
    
    贝塞尔曲线的计算公式如下：
    
\begin{equation*}
    \sum_{i=0}^{n}\binom{n}{i}P_i{(1-t)}^{n-i}t_i
\end{equation*}
    
    其中n为该贝塞尔曲线的阶数，i为二项式参数，t为控制点在相邻两点的线段上所占的比例。将比例参数t在区间[0, 1]上遍历一次，即可得到完整的贝塞尔曲线。
    \subsection{贝塞尔曲面}
    贝塞尔曲面\cite{khan2019bezier}可以理解为时贝塞尔曲线从二维到三维的过程。将n*m个顶点在水平方向上(即忽略高度)，分为n行m列，每一列的顶点，都可以根据贝塞尔曲线的计算公式得到1个最阶数的控制点，令其比例参数为t1，总共得到m个控制点。然后再根据贝塞尔曲线的公式对该m个控制点计算，令其比例参数为t2，则又可以得到1个最高次的控制点，该控制点即为贝塞尔曲线上的1个点.然后遍历所有两次贝塞尔曲线的计算情况(即遍历2个计算参数t1和t2所有的情况)，即可得到完整的贝塞尔曲面。
\begin{figure}[ht]
    \centering
    \includegraphics[height=5cm]{images/贝塞尔曲面.jpg}
    \caption{贝塞尔曲面}
    \label{fig:my_label}
\end{figure}
	\section{曲面细分}
	曲面细分于4.x版本加入OpenGL，可以通过参数设定和算法编写增加模型的顶点数，并将模型的面划分为更多更小的面，从而提高模型的精度。同时由于顶点数和面数的增加，曲面细分对计算能力的需求也变得更大。
\begin{figure}[ht]
    \centering
    \includegraphics[height=5cm]{images/曲面细分示例.png}
    \caption{曲面细分示例}
    \label{fig:my_label}
\end{figure}

    启用曲面细分时，OpenGL调用绘制函数不再传入通常的Triangle等图元类型，而是传入Patch这一特殊的图元类型，并由开发人员设置组成一个Patch所需的顶点数。而当一个Patch图元被传入渲染线管后，除了顶点着色器、片段着色器这种改写渲染管线常见的部分以外，还会启用与曲面细分相关的部分。总的来说主要包括曲面细分控制着色器(Tessellation Control Shader)，固定曲面细分引擎(Fixed-function Tessellation Engine)，曲面细分计算着色器(Tessellation Evaluation Shader)。
    \subsection{曲面细分控制着色器}
    曲面细分控制着色器主要执行两个任务：
    
    一是控制曲面细分的程度。曲面细分控制着色分别通过指定TessLevelInner和TessLevelOuter两个内建数组的值，控制后续细分空间的划分。其中，TessLevelInner控制细分空间内的空间划分，TessLevelOuter控制细分空间的边界划分。
    
    二是生成输出Patch顶点。曲面细分控制着色器输入一组Patch顶点后，经过一定的处理，会再输出一组新的Patch顶点，即控制点。开发人员可以在这一过程中对输入Patch顶点进行增删改，并计算出控制点的各项属性值。这些控制点及相应的属性值会在后续的曲面细分计算着色器中进行计算处理。
    \subsection{曲面细分引擎}
    曲面细分引擎是OpenGL渲染线管的一个固定阶段，只有当曲面细分计算着色器处于活动状态时才会启动。其负责从曲面细分控制着色器的输出Patch顶点中生成一组新的图元，图元的生成受到曲面细分程度(即TessLevelInner和TessLevelOuter的值)，曲面细分计算着色器中设置的空间划分方式、图元类型等参数的影响。特别是，当被划分的区域为三角形时，会根据该三角形对应的质心坐标系生成一系列的点，并将所有的点相连，形成许多较小的三角形面，并且该三角形的质心会作为输入，传入到曲面细分计算着色器中。
    \subsection{曲面细分计算着色器}
    曲面细分计算着色器类似于顶点着色器，每次只能输出一个顶点，即每次通过前面阶段得到的控制点只能计算出一个新的顶点。该顶点的计算需要传入的质心坐标参与，而具体的计算算法由开发人员自行编写决定，不同的算法最后会产生不同的细分效果。目前业界常见的计算算法有Loop细分\cite{gu2018novel}，Clark细分\cite{ghandour2020performance}，Phong细分，PN三角形细分。
	\section{凹凸贴图，法线贴图，置换贴图}
	为了在渲染时给用户提供真实的视觉体验，往往会为模型绘制包含额外信息的贴图，从而增加模型表面的细节和层次感。根据额外信息的作方式以及细节层次的真伪，可以将该作用的贴图分为不同的种类，包括凹凸贴图、法线贴图、置换贴图等。
	\subsection{凹凸贴图}
	凹凸贴图通常是一种只有8-bit的灰度图，其灰度值代表着模型表面的凹凸程度。当灰度值越接近“黑色”时，代表模型对应位置“凹陷”程度越高，当灰度值越接近“白色”时，代表模型对应位置“凸出”程度越高。灰度值的大小会影响光照在此处的作用效果，制造不同程度的阴影，从而带来凹凸不平的观感，因此其所制造的细节是一种假象，仅仅具有视觉效果，并没有改变模型本身。凹凸贴图在处理类似于毛孔、皱纹这种细小部分时会有比较好的效果。
	\subsection{法线贴图}
	法线贴图可以看作是在凹凸贴图基础上的一种提高，一般为RGB的彩色图，(R, G, B)三个分量分别对应法线向量的(x, y, z)三个分量，其制造出的细节也是一种假象，没有改变模型本身。在实际的渲染过程中，光照在模型表面的作用效果很大程度上受到法线朝向的影响(最后的光照效果需要光照方向和法线方向参与计算)，利用这个原理可以控制模型表面的光影，从而在视觉上丰富模型表面的细节层次。法线贴图中最常用的是切线空间法线贴图。
	\subsection{置换贴图}
	置换贴图\cite{zirr2019distortion}通常也是8-bit的灰度图，其包含了顶点在对应方向上的偏移量，作用在模型上后，会改变模型顶点上的位置信息，因此，置换贴图所制造出的细节或者层次感是在物理层面上的改变。目前主要的做法是进行高低模烘培，将二者的差异程度作为偏移量，然后作用在低模上，从而丰富低模表面的细节和轮廓。